home *** CD-ROM | disk | FTP | other *** search
- /*
- * hook.c: Does those naughty hook functions.
- *
- * Written By Michael Sandrof
- *
- * Copyright(c) 1990
- *
- * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
- */
-
- /*
- * april 11, 1998
- * patched do_hook() overflow - nyt
- */
-
-
- #ifndef lint
- static char rcsid[] = "@(#)$Id: hook.c,v 1.37 1997/04/21 06:34:00 mrg Exp $";
- #endif /* lint */
-
- #include "irc.h"
-
- #include "hook.h"
- #include "vars.h"
- #include "ircaux.h"
- #include "alias.h"
- #include "list.h"
- #include "window.h"
- #include "server.h"
- #include "output.h"
- #include "edit.h"
-
- #ifdef INCLUDE_UNUSED_FUNCTIONS
- static void flush_on_hooks _((void));
- #endif /* INCLUDE_UNUSED_FUNCTIONS */
- static char *fill_it_out _((char *, int));
- static void setup_struct _((int, int, int, int));
- static int Add_Remove_Check _((List *, char *));
- static int Add_Remove_Check_List _((List *, List*));
- static void add_numeric_hook _((int, char *, char *, int, int, int, int));
- static void add_hook _((int, char *, char *, int, int, int, int));
- static int show_numeric_list _((int));
- static int show_list _((int));
- static void remove_numeric_hook _((int, char *, int, int, int));
- static void write_hook _((FILE *, Hook *, char *));
-
- #define SILENT 0
- #define QUIET 1
- #define NORMAL 2
- #define NOISY 3
-
- /*
- * The various ON levels: SILENT means the DISPLAY will be OFF and it will
- * suppress the default action of the event, QUIET means the display will be
- * OFF but the default action will still take place, NORMAL means you will be
- * notified when an action takes place and the default action still occurs,
- * NOISY means you are notified when an action occur plus you see the action
- * in the display and the default actions still occurs
- */
- static char *noise_level[] = { "SILENT", "QUIET", "NORMAL", "NOISY" };
-
- #define HS_NOGENERIC 0x1000
- #define HF_LOOKONLY 0x0001
- #define HF_NORECURSE 0x0002
- #define HF_GLOBAL 0x0004
-
- extern int load_depth;
-
- int in_on_who = 0;
-
- NumericList *numeric_list = (NumericList *) 0;
- /* hook_functions: the list of all hook functions available */
- HookFunc FAR hook_functions[] =
- {
- { "ACTION", (Hook *) 0, 3, 0, 0 },
- { "CHANNEL_NICK", (Hook *) 0, 3, 0, 0 },
- { "CHANNEL_SIGNOFF", (Hook *) 0, 3, 0, 0 },
- { "CONNECT", (Hook *) 0, 1, 0, 0 },
- { "CTCP", (Hook *) 0, 4, 0, 0 },
- { "CTCP_REPLY", (Hook *) 0, 3, 0, 0 },
- { "DCC_CHAT", (Hook *) 0, 2, 0, 0 },
- { "DCC_CONNECT", (Hook *) 0, 2, 0, 0 },
- { "DCC_ERROR", (Hook *) 0, 6, 0, 0 },
- { "DCC_LOST", (Hook *) 0, 2, 0, 0 },
- { "DCC_RAW", (Hook *) 0, 3, 0, 0 },
- { "DCC_REQUEST", (Hook *) 0, 4, 0, 0 },
- { "DISCONNECT", (Hook *) 0, 1, 0, 0 },
- { "ENCRYPTED_NOTICE", (Hook *) 0, 3, 0, 0 },
- { "ENCRYPTED_PRIVMSG", (Hook *) 0, 3, 0, 0 },
- { "EXEC", (Hook *) 0, 2, 0, 0 },
- { "EXEC_ERRORS", (Hook *) 0, 2, 0, 0 },
- { "EXEC_EXIT", (Hook *) 0, 3, 0, 0 },
- { "EXEC_PROMPT", (Hook *) 0, 2, 0, 0 },
- { "EXIT", (Hook *) 0, 1, 0, 0 },
- { "FLOOD", (Hook *) 0, 3, 0, 0 },
- { "HELP", (Hook *) 0, 2, 0, 0 },
- { "HOOK", (Hook *) 0, 1, 0, 0 },
- { "IDLE", (Hook *) 0, 1, 0, 0 },
- { "INPUT", (Hook *) 0, 1, 0, 0 },
- { "INVITE", (Hook *) 0, 2, 0, 0 },
- { "JOIN", (Hook *) 0, 2, 0, 0 },
- { "KICK", (Hook *) 0, 3, 0, HF_LOOKONLY },
- { "LEAVE", (Hook *) 0, 2, 0, 0 },
- { "LIST", (Hook *) 0, 3, 0, HF_LOOKONLY },
- { "MAIL", (Hook *) 0, 2, 0, 0 },
- { "MODE", (Hook *) 0, 3, 0, 0 },
- { "MSG", (Hook *) 0, 2, 0, 0 },
- { "MSG_GROUP", (Hook *) 0, 3, 0, 0 },
- { "NAMES", (Hook *) 0, 2, 0, HF_LOOKONLY },
- { "NICKNAME", (Hook *) 0, 2, 0, 0 },
- { "NOTE", (Hook *) 0, 10, 0, 0 },
- { "NOTICE", (Hook *) 0, 2, 0, 0 },
- { "NOTIFY_SIGNOFF", (Hook *) 0, 1, 0, 0 },
- { "NOTIFY_SIGNON", (Hook *) 0, 1, 0, 0 },
- { "PUBLIC", (Hook *) 0, 3, 0, 0 },
- { "PUBLIC_MSG", (Hook *) 0, 3, 0, 0 },
- { "PUBLIC_NOTICE", (Hook *) 0, 3, 0, 0 },
- { "PUBLIC_OTHER", (Hook *) 0, 3, 0, 0 },
- { "RAW_IRC", (Hook *) 0, 1, 0, 0 },
- { "SEND_ACTION", (Hook *) 0, 2, 0, 0 },
- { "SEND_DCC_CHAT", (Hook *) 0, 2, 0, 0 },
- { "SEND_MSG", (Hook *) 0, 2, 0, 0 },
- { "SEND_NOTICE", (Hook *) 0, 2, 0, 0 },
- { "SEND_PUBLIC", (Hook *) 0, 2, 0, 0 },
- { "SEND_TALK", (Hook *) 0, 2, 0, 0 },
- { "SERVER_NOTICE", (Hook *) 0, 1, 0, 0 },
- { "SIGNOFF", (Hook *) 0, 1, 0, 0 },
- { "TALK", (Hook *) 0, 2, 0, 0 },
- { "TIMER", (Hook *) 0, 1, 0, 0 },
- { "TOPIC", (Hook *) 0, 2, 0, 0 },
- { "WALL", (Hook *) 0, 2, 0, HF_LOOKONLY },
- { "WALLOP", (Hook *) 0, 3, 0, HF_LOOKONLY },
- { "WHO", (Hook *) 0, 6, 0, HF_LOOKONLY },
- { "WIDELIST", (Hook *) 0, 1, 0, HF_LOOKONLY },
- { "WINDOW", (Hook *) 0, 2, 0, HF_NORECURSE },
- { "WINDOW_KILL", (Hook *) 0, 1, 0, 0 }
- };
-
- static char *
- fill_it_out(str, params)
- char *str;
- int params;
- {
- char buffer[BIG_BUFFER_SIZE + 1];
- char *arg,
- *free_ptr = (char *) 0,
- *ptr;
- int i = 0;
-
- malloc_strcpy(&free_ptr, str);
- ptr = free_ptr;
- *buffer = (char) 0;
- while ((arg = next_arg(ptr, &ptr)) != NULL)
- {
- if (*buffer)
- strmcat(buffer, " ", BIG_BUFFER_SIZE);
- strmcat(buffer, arg, BIG_BUFFER_SIZE);
- if (++i == params)
- break;
- }
- for (; i < params; i++)
- strmcat(buffer, (i < params-1) ? " %" : " *", BIG_BUFFER_SIZE);
- if (*ptr)
- {
- strmcat(buffer, " ", BIG_BUFFER_SIZE);
- strmcat(buffer, ptr, BIG_BUFFER_SIZE);
- }
- malloc_strcpy(&free_ptr, buffer);
- return (free_ptr);
- }
-
-
- /*
- * A variety of comparison functions used by the hook routines follow.
- */
-
- struct CmpInfoStruc
- {
- int ServerRequired;
- int SkipSerialNum;
- int SerialNumber;
- int Flags;
- } cmp_info;
-
- #define CIF_NOSERNUM 0x0001
- #define CIF_SKIP 0x0002
-
- int cmpinfodone = 0;
-
- static void
- setup_struct(ServReq, SkipSer, SerNum, flags)
- int ServReq;
- int SkipSer;
- int SerNum;
- int flags;
- {
- cmp_info.ServerRequired = ServReq;
- cmp_info.SkipSerialNum = SkipSer;
- cmp_info.SerialNumber = SerNum;
- cmp_info.Flags = flags;
- }
-
- static int
- Add_Remove_Check(_Item, Name)
- List *_Item;
- char *Name;
- {
- int comp;
- Hook *Item = (Hook *)_Item;
-
- if (cmp_info.SerialNumber != Item->sernum)
- return (Item->sernum > cmp_info.SerialNumber) ? 1 : -1;
- if ((comp = my_stricmp(Item->nick, Name)) != 0)
- return comp;
- if (Item->server != cmp_info.ServerRequired)
- return (Item->server > cmp_info.ServerRequired) ? 1 : -1;
- return 0;
- }
-
- static int
- Add_Remove_Check_List(_Item, _Item2)
- List *_Item;
- List *_Item2;
- {
- return Add_Remove_Check(_Item, _Item->name);
- }
-
- static void
- add_numeric_hook(numeric, nick, stuff, noisy, not, server, sernum)
- int numeric;
- char *nick,
- *stuff;
- int noisy,
- not;
- int server,
- sernum;
- {
- NumericList *entry;
- Hook *new;
- char buf[4];
-
- sprintf(buf, "%3.3u", numeric);
- if ((entry = (NumericList *) find_in_list((List **) &numeric_list, buf, 0)) ==
- (NumericList *) 0)
- {
- entry = (NumericList *) new_malloc(sizeof(NumericList));
- entry->name = (char *) 0;
- entry->list = (Hook *) 0;
- malloc_strcpy(&(entry->name), buf);
- add_to_list((List **) &numeric_list, (List *) entry);
- }
-
- setup_struct((server==-1) ? -1 : (server & ~HS_NOGENERIC), sernum-1, sernum, 0);
- if ((new = (Hook *) remove_from_list_ext((List **) &(entry->list), nick, Add_Remove_Check)) != NULL)
- {
- new->not = 1;
- new_free(&(new->nick));
- new_free(&(new->stuff));
- wait_new_free((char **) &new);
- }
- new = (Hook *) new_malloc(sizeof(Hook));
- new->nick = (char *) 0;
- new->noisy = noisy;
- new->server = server;
- new->sernum = sernum;
- new->not = not;
- new->global = loading_global;
- new->stuff = (char *) 0;
- malloc_strcpy(&new->nick, nick);
- malloc_strcpy(&new->stuff, stuff);
- upper(new->nick);
- add_to_list_ext((List **) &(entry->list), (List *) new, Add_Remove_Check_List);
- }
-
- /*
- * add_hook: Given an index into the hook_functions array, this adds a new
- * entry to the list as specified by the rest of the parameters. The new
- * entry is added in alphabetical order (by nick).
- */
- static void
- add_hook(which, nick, stuff, noisy, not, server, sernum)
- int which;
- char *nick,
- *stuff;
- int noisy,
- not;
- int server,
- sernum;
- {
- Hook *new;
-
- if (which < 0)
- {
- add_numeric_hook(-which, nick, stuff, noisy, not, server,
- sernum);
- return;
- }
- setup_struct((server == -1) ? -1 : (server & ~HS_NOGENERIC), sernum-1, sernum, 0);
- if ((new = (Hook *) remove_from_list_ext((List **) &(hook_functions[which].list), nick, Add_Remove_Check)) != NULL)
- {
- new->not = 1;
- new_free(&(new->nick));
- new_free(&(new->stuff));
- wait_new_free((char **) &new);
- }
- new = (Hook *) new_malloc(sizeof(Hook));
- new->nick = (char *) 0;
- new->noisy = noisy;
- new->server = server;
- new->sernum = sernum;
- new->not = not;
- new->stuff = (char *) 0;
- new->global = loading_global;
- malloc_strcpy(&new->nick, nick);
- malloc_strcpy(&new->stuff, stuff);
- upper(new->nick);
- add_to_list_ext((List **) &(hook_functions[which].list), (List *) new, Add_Remove_Check_List);
- }
-
- /* show_hook shows a single hook */
- extern void
- show_hook(list, name)
- Hook *list;
- char *name;
- {
- if (list->server != -1)
- say("On %s from \"%s\" do %s [%s] <%d> (Server %d)%s",
- name, list->nick,
- (list->not ? "nothing" : list->stuff),
- noise_level[list->noisy], list->sernum,
- list->server&~HS_NOGENERIC,
- (list->server&HS_NOGENERIC) ? " Exclusive" : empty_string);
- else
- say("On %s from \"%s\" do %s [%s] <%d>",
- name, list->nick,
- (list->not ? "nothing" : list->stuff),
- noise_level[list->noisy],
- list->sernum);
- }
-
- /*
- * show_numeric_list: If numeric is 0, then all numeric lists are displayed.
- * If numeric is non-zero, then that particular list is displayed. The total
- * number of entries displayed is returned
- */
- static int
- show_numeric_list(numeric)
- int numeric;
- {
- NumericList *tmp;
- Hook *list;
- char buf[4];
- int cnt = 0;
-
- if (numeric)
- {
- sprintf(buf, "%3.3u", numeric);
- if ((tmp = (NumericList *) find_in_list((List **) &numeric_list, buf, 0))
- != NULL)
- {
- for (list = tmp->list; list; list = list->next, cnt++)
- show_hook(list, tmp->name);
- }
- }
- else
- {
- for (tmp = numeric_list; tmp; tmp = tmp->next)
- {
- for (list = tmp->list; list; list = list->next, cnt++)
- show_hook(list, tmp->name);
- }
- }
- return (cnt);
- }
-
- /*
- * show_list: Displays the contents of the list specified by the index into
- * the hook_functions array. This function returns the number of entries in
- * the list displayed
- */
- static int
- show_list(which)
- int which;
- {
- Hook *list;
- int cnt = 0;
-
- /* Less garbage when issueing /on without args. (lynx) */
- for (list = hook_functions[which].list; list; list = list->next, cnt++)
- show_hook(list, hook_functions[which].name);
- return (cnt);
- }
-
- /*
- * do_hook: This is what gets called whenever a MSG, INVITES, WALL, (you get
- * the idea) occurs. The nick is looked up in the appropriate list. If a
- * match is found, the stuff field from that entry in the list is treated as
- * if it were a command. First it gets expanded as though it were an alias
- * (with the args parameter used as the arguments to the alias). After it
- * gets expanded, it gets parsed as a command. This will return as its value
- * the value of the noisy field of the found entry, or -1 if not found.
- */
- /* huh-huh.. this sucks.. im going to re-write it so that it works */
- /*VARARGS*/
- int
- #ifdef HAVE_STDARG_H
- do_hook(int which, char *format, ...)
- {
- va_list vl;
- #else
- do_hook(which, format, arg1, arg2, arg3, arg4, arg5, arg6)
- int which;
- char *format;
- char *arg1,
- *arg2,
- *arg3,
- *arg4,
- *arg5,
- *arg6;
- {
- #endif /* HAVE_STDARG_H */
- Hook *tmp, **list;
- char buffer[2*BIG_BUFFER_SIZE + 1],
- *name = (char *) 0;
- int RetVal = 1;
- unsigned int display;
- int i,
- old_in_on_who;
- Hook *hook_array[2048];
- int hook_num = 0;
- static int hook_level = 0;
- int len;
- char *foo;
-
- hook_level++;
- bzero(buffer, sizeof(buffer));
-
- #ifdef HAVE_STDARG_H
- va_start(vl, format);
- vsprintf(buffer, format, vl);
- va_end(vl);
- #else
- sprintf(buffer, format, arg1, arg2, arg3, arg4, arg5, arg6);
- #endif /* HAVE_STDARG_H */
- if (which < 0)
- {
- NumericList *hook;
- char buf[4];
-
- sprintf(buf, "%3.3u", -which);
- if ((hook = (NumericList *) find_in_list((List **) &numeric_list, buf, 0))
- != NULL)
- {
- name = hook->name;
- list = &hook->list;
- }
- else
- list = (Hook **) 0;
- }
- else
- {
- if (hook_functions[which].mark && (hook_functions[which].flags & HF_NORECURSE))
- list = (Hook **) 0;
- else
- {
- list = &(hook_functions[which].list);
- name = hook_functions[which].name;
- }
- }
- if (!list)
- return really_free(--hook_level), 1;
-
- if (which >= 0)
- hook_functions[which].mark++;
- /* not attached, so dont "fix" it */
- {
- int currser = 0, oldser = 0;
- int currmatch = 0, oldmatch = 0;
- Hook *bestmatch = (Hook *) 0;
- int nomorethisserial = 0;
-
- for (tmp = *list;tmp;tmp = tmp->next)
- {
- currser = tmp->sernum;
- if (currser != oldser) /* new serial number */
- {
- oldser = currser;
- currmatch = oldmatch = nomorethisserial = 0;
- if (bestmatch)
- hook_array[hook_num++] = bestmatch;
- bestmatch = (Hook *) 0;
- }
-
- if (nomorethisserial)
- continue;
- /* if there is a specific server
- hook and it doesnt match, then
- we make sure nothing from
- this serial number gets hooked */
- if ((tmp->server != -1) &&
- (tmp->server & HS_NOGENERIC) &&
- (tmp->server != (from_server & HS_NOGENERIC)))
- {
- nomorethisserial = 1;
- bestmatch = (Hook *) 0;
- continue;
- }
- currmatch = wild_match(tmp->nick,buffer);
- if (currmatch > oldmatch)
- {
- oldmatch = currmatch;
- bestmatch = tmp;
- }
- }
- if (bestmatch)
- hook_array[hook_num++] = bestmatch;
- }
-
- for (i = 0; i < hook_num; i++)
- {
- tmp = hook_array[i];
- if (!tmp)
- {
- if (which >= 0)
- hook_functions[which].mark--;
- return really_free(--hook_level), RetVal;
- }
- if (tmp->not)
- continue;
- send_text_flag = which;
- if (tmp->noisy > QUIET)
- say("%s activated by \"%s\"", name, buffer);
- display = window_display;
- if (tmp->noisy < NOISY)
- window_display = 0;
-
- save_message_from();
- old_in_on_who = in_on_who;
- if (which == WHO_LIST || (which <= -311 && which >= -318))
- in_on_who = 1;
- len = strlen(tmp->stuff) + 1;
- foo = new_malloc(len);
- bcopy(tmp->stuff, foo, len);
- parse_line((char *) 0, foo, buffer, 0, 0);
- new_free(&foo);
- in_on_who = old_in_on_who;
- window_display = display;
- send_text_flag = -1;
- restore_message_from();
- if (!tmp->noisy && !tmp->sernum)
- RetVal = 0;
- }
- if (which >= 0)
- hook_functions[which].mark--;
- return really_free(--hook_level), RetVal;
- }
-
- static void
- remove_numeric_hook(numeric, nick, server, sernum, quiet)
- int numeric;
- char *nick;
- int server;
- int sernum;
- int quiet;
- {
- NumericList *hook;
- Hook *tmp,
- *next;
- char buf[4];
-
- sprintf(buf, "%3.3u", numeric);
- if ((hook = (NumericList *) find_in_list((List **) &numeric_list, buf,0)) != NULL)
- {
- if (nick)
- {
- setup_struct((server == -1) ? -1 :
- (server & ~HS_NOGENERIC), sernum - 1, sernum, 0);
- if ((tmp = (Hook *) remove_from_list((List **) &(hook->list), nick)) != NULL)
- {
- if (!quiet)
- say("\"%s\" removed from %s list", nick, buf);
- tmp->not = 1;
- new_free(&(tmp->nick));
- new_free(&(tmp->stuff));
- wait_new_free((char **) &tmp);
- if (hook->list == (Hook *) 0)
- {
- if ((hook = (NumericList *) remove_from_list((List **) &numeric_list, buf)) != NULL)
- {
- new_free(&(hook->name));
- new_free(&hook);
- }
- }
- return;
- }
- }
- else
- {
- for (tmp = hook->list; tmp; tmp = next)
- {
- next = tmp->next;
- tmp->not = 1;
- new_free(&(tmp->nick));
- new_free(&(tmp->stuff));
- wait_new_free((char **) &tmp);
- }
- hook->list = (Hook *) 0;
- if (!quiet)
- say("The %s list is empty", buf);
- return;
- }
- }
- if (quiet)
- return;
- if (nick)
- say("\"%s\" is not on the %s list", nick, buf);
- else
- say("The %s list is empty", buf);
- }
-
- #ifdef INCLUDE_UNUSED_FUNCTIONS
- static void
- flush_on_hooks()
- {
- int x;
- int old_display = window_display;
-
- window_display = 0;
- for (x = 100 ; x < 999; x++)
- remove_numeric_hook(x, (char *) 0, 1, x, 0);
- for (x = 0 ; x < NUMBER_OF_LISTS; x++)
- remove_hook(x, (char *) 0, 1, x, 0);
- window_display = old_display;
- }
- #endif /* INCLUDE_UNUSED_FUNCTIONS */
-
- extern void
- remove_hook(which, nick, server, sernum, quiet)
- int which;
- char *nick;
- int server,
- sernum,
- quiet;
- {
- Hook *tmp,
- *next;
-
- if (which < 0)
- {
- remove_numeric_hook(-which, nick, server, sernum, quiet);
- return;
- }
- if (nick)
- {
- setup_struct((server == -1) ? -1 : (server & ~HS_NOGENERIC),
- sernum-1, sernum, 0);
- if ((tmp = (Hook *) remove_from_list_ext((List **) &hook_functions[which].list, nick, Add_Remove_Check)) != NULL)
- {
- if (!quiet)
- say("\"%s\" removed from %s list", nick, hook_functions[which].name);
- tmp->not = 1;
- new_free(&(tmp->nick));
- new_free(&(tmp->stuff));
- wait_new_free((char **) &tmp);
- }
- else if (!quiet)
- say("\"%s\" is not on the %s list", nick, hook_functions[which].name);
- }
- else
- {
- for(tmp = hook_functions[which].list; tmp; tmp=next)
- {
- next = tmp->next;
- tmp->not = 1;
- new_free(&(tmp->nick));
- new_free(&(tmp->stuff));
- wait_new_free((char **) &tmp);
- }
- hook_functions[which].list = (Hook *) 0;
- if (!quiet)
- say("The %s list is empty", hook_functions[which].name);
- }
- }
-
- /* on: The ON command */
- /*ARGSUSED*/
- void
- on(command, args, subargs)
- char *command,
- *args,
- *subargs;
- {
- char *func,
- *nick,
- *serial,
- *cmd = (char *) 0;
- /* int noisy = NORMAL, not = 0, remove = 0, -not used */
- int noisy,
- not,
- server,
- sernum,
- remove,
- len,
- which = 0,
- cnt,
- i;
-
- if (get_int_var(NOVICE_VAR) && !load_depth)
- {
- yell("*** You may not type ON commands when you have the NOVICE");
- yell("*** variable set to ON. Some ON commands may cause a");
- yell("*** security breach on your machine, or enable another");
- yell("*** user to control your IRC session. Read the help files");
- yell("*** in /HELP ON before using ON");
- return;
- }
- if ((func = next_arg(args, &args)) != NULL)
- {
- if (*func == '#')
- {
- if (!(serial = next_arg(args, &args)))
- {
- say("No serial number specified");
- return;
- }
- sernum = atoi(serial);
- func++;
- }
- else
- sernum = 0;
- switch (*func)
- {
- case '&':
- server = from_server;
- func++;
- break;
- case '@':
- server = from_server|HS_NOGENERIC;
- func++;
- break;
- default:
- server = -1;
- break;
- }
- switch (*func)
- {
- case '-':
- noisy = QUIET;
- func++;
- break;
- case '^':
- noisy = SILENT;
- func++;
- break;
- case '+':
- noisy = NOISY;
- func++;
- break;
- default:
- noisy = NORMAL;
- break;
- }
- if ((len = strlen(func)) == 0)
- {
- say("You must specify an event type!");
- return;
- }
- malloc_strcpy(&cmd, func);
- upper(cmd);
- for (cnt = 0, i = 0; i < NUMBER_OF_LISTS; i++)
- {
- if (!strncmp(cmd, hook_functions[i].name, len))
- {
- if (strlen(hook_functions[i].name) == len)
- {
- cnt = 1;
- which = i;
- break;
- }
- else
- {
- cnt++;
- which = i;
- }
- }
- else if (cnt)
- break;
- }
- if (cnt == 0)
- {
- if (is_number(cmd))
- {
- which = atoi(cmd);
- if ((which < 0) || (which > 999))
- {
- say("Numerics must be between 001 and 999");
- goto out;
- }
- which = -which;
- }
- else
- {
- say("No such ON function: %s", func);
- goto out;
- }
- }
- else if (cnt > 1)
- {
- say("Ambiguous ON function: %s", func);
- goto out;
- }
- else
- {
- if (get_int_var(INPUT_PROTECTION_VAR) && !my_strnicmp(hook_functions[which].name, "INPUT", 5))
- {
- say("You cannot use /ON INPUT with INPUT_PROTECTION set");
- say("Please read /HELP ON INPUT, and /HELP SET INPUT_PROTECTION");
- goto out;
- }
- }
- remove = 0;
- not = 0;
- switch (*args)
- {
- case '-':
- remove = 1;
- args++;
- break;
- case '^':
- not = 1;
- args++;
- break;
- }
- if ((nick = new_next_arg(args, &args)) != NULL)
- {
- if (which < 0)
- nick = fill_it_out(nick, 1);
- else
- nick = fill_it_out(nick,
- hook_functions[which].params);
- if (remove)
- {
- if (strlen(nick) == 0)
- say("No expression specified");
- else
- remove_hook(which, nick, server,
- sernum, 0);
- }
- else
- {
- if (not)
- args = empty_string;
- if (*nick)
- {
- if (*args == LEFT_BRACE)
- {
- char *ptr = MatchingBracket(++args,
- LEFT_BRACE, RIGHT_BRACE);
- if (!ptr)
- {
- say("Unmatched brace in ON");
- new_free(&nick);
- goto out;
- }
- else if (ptr[1])
- {
- say("Junk after closing brace in ON");
- new_free(&nick);
- goto out;
- }
- else
- *ptr = '\0';
- }
- add_hook(which, nick, args, noisy, not, server, sernum);
- if (which < 0)
- say("On %3.3u from \"%s\" do %s [%s] <%d>",
- -which, nick, (not ? "nothing" : args),
- noise_level[noisy], sernum);
- else
- say("On %s from \"%s\" do %s [%s] <%d>",
- hook_functions[which].name, nick,
- (not ? "nothing" : args),
- noise_level[noisy], sernum);
- }
- }
- new_free(&nick);
- }
- else
- {
- if (remove)
- remove_hook(which, (char *) 0, server,
- sernum, 0);
- else
- {
- if (which < 0)
- {
- if (show_numeric_list(-which) == 0)
- say("The %3.3u list is empty.",
- -which);
- }
- else if (show_list(which) == 0)
- say("The %s list is empty.",
- hook_functions[which].name);
- }
- }
- }
- else
- {
- int total = 0;
-
- say("ON listings:");
- for (which = 0; which < NUMBER_OF_LISTS; which++)
- total += show_list(which);
- total += show_numeric_list(0);
- if (total == 0)
- say("All ON lists are empty.");
- }
- out:
- new_free(&cmd);
- }
-
- static void
- write_hook(fp, hook, name)
- FILE *fp;
- Hook *hook;
- char *name;
- {
- char *stuff = (char *) 0;
-
- if (hook->server!=-1)
- return;
- switch (hook->noisy)
- {
- case SILENT:
- stuff = "^";
- break;
- case QUIET:
- stuff = "-";
- break;
- case NORMAL:
- stuff = empty_string;
- break;
- case NOISY:
- stuff = "+";
- break;
- }
- if (hook->sernum)
- fprintf(fp, "ON #%s%s %d \"%s\"", stuff, name, hook->sernum,
- hook->nick);
- else
- fprintf(fp, "ON %s%s \"%s\"", stuff, name, hook->nick);
- fprintf(fp, " %s\n", hook->stuff);
- }
-
- /*
- * save_hooks: for use by the SAVE command to write the hooks to a file so it
- * can be interpreted by the LOAD command
- */
- void
- save_hooks(fp, do_all)
- FILE *fp;
- int do_all;
- {
- Hook *list;
- NumericList *numeric;
- int which;
-
- for (which = 0; which < NUMBER_OF_LISTS; which++)
- {
- for (list = hook_functions[which].list; list; list = list->next)
- if (!list->global || do_all)
- write_hook(fp,list, hook_functions[which].name);
- }
- for (numeric = numeric_list; numeric; numeric = numeric->next)
- {
- for (list = numeric->list; list; list = list->next)
- if (!list->global)
- write_hook(fp, list, numeric->name);
- }
- }
-